/*
Metakosmos
2011 Chad McKinney with Curtis McKinney and Cole Ingraham, as Glich Lich
A piece using a metaverse of SuperCollider tweets.

Metakosmos.new;
*/

// MetaOSC sends,receives, and parses network messages between SC and OSCthulhu. 
MetaOSC {
	
	var netAddr,addSyncResponder,setSyncResponder,removeSyncResponder,addPeerResponder,removePeerResponder,chatResponder;
	var mMetaLogic,syncActiveArray,syncReserveArray,syncReserveBoolArray,syncActiveBoolArray;
	
	/*
	MetaOSC constructor
	@param logic The MetaLogic instance we use to organize the logic of the piece
	*/
	*new { |metaLogic|
		^super.new.init(metaLogic);
	}
	
	init { |metaLogic|
		mMetaLogic = metaLogic;
		netAddr = NetAddr.new("127.0.0.1", 32243);
		syncActiveBoolArray = [false,false];
		syncReserveBoolArray = [false,false];
		syncActiveArray = [0,0];
		syncReserveArray = [0,0];
		
		addSyncResponder = OSCresponderNode.new(nil,'/addSyncObject', { 
			|time,resp,msg|
			//[time,resp,msg].postln;
		}).add;
		
		setSyncResponder = OSCresponderNode.new(nil,'/setSyncArg', { 
			|time,resp,msg|
			msg.postln;
			case
			{ msg[1] == 'reserveArray' }
			{
				//mMetaLogic.syncTweetReserveState(msg[2],msg[3]);
				syncReserveArray = syncReserveArray.put(msg[2],msg[3]);
				syncReserveBoolArray = syncReserveBoolArray.put(msg[2],true);
				if((syncReserveBoolArray[0] == true) && (syncReserveBoolArray[1] == true),
				{
					syncReserveArray = MetaCrypt.decodeBitArray(syncReserveArray);
					syncReserveArray.size.postln;
					mMetaLogic.syncReserveArray(syncReserveArray);
					syncReserveArray = [0,0];
					syncReserveBoolArray = [false,false];
				});
			}
			{ msg[1] == 'activeArray' }
			{
				syncActiveArray = syncActiveArray.put(msg[2],msg[3]);
				syncActiveBoolArray = syncActiveBoolArray.put(msg[2],true);
				if((syncActiveBoolArray[0] == true) && (syncActiveBoolArray[1] == true),
				{
					//syncActiveArray.postln;
					//syncActiveBoolArray.postln;
					syncActiveArray = MetaCrypt.decodeBitArray(syncActiveArray);
					//syncActiveArray.postln;
					mMetaLogic.syncActiveArray(syncActiveArray);
					syncActiveArray = [0,0];
					syncActiveBoolArray = [false,false];
				});
				
			};
		}).add;
		
		removeSyncResponder = OSCresponderNode.new(nil,'/removeSyncObject', { 
			|time,resp,msg|
			//[time,resp,msg].postln;
		}).add;
		
		addPeerResponder = OSCresponderNode.new(nil,'/addPeer', { 
			|time,resp,msg|
			//[time,resp,msg].postln;
		}).add;
		
		removePeerResponder = OSCresponderNode.new(nil,'/removePeer', { 
			|time,resp,msg|
			//[time,resp,msg].postln;
		}).add;
		
		chatResponder = OSCresponderNode.new(nil,'/chat', { 
			|time,resp,msg|
			//[time,resp,msg].postln;
		}).add;
		
		netAddr.sendMsg("/login");
		netAddr.sendMsg("/changePorts",57120);
		netAddr.sendMsg("/addSyncObject", "initFlag", "SCObject", "flag", 0);
		{ 1.wait; this.trySetup; }.fork;
	}
	
	// Attempt to set up the network environment
	trySetup {
		// Query the status of intialization. If we're not initialized, do so now.
		if(mMetaLogic.initFlag == 0,{
			mMetaLogic.initFlag = 1; 
			netAddr.sendMsg("/setSyncArg", "initFlag", 0, 1); 
			// reserve array objects. MetaCrypt Packed Binary array that describes the state of the object, SIZE IS CURRENTLY 51
			netAddr.sendMsg("/addSyncObject", "reserveArray", "SCObject", "tweetObject",-1, 8388607);
			// active array objects. MetaCrypt Packed Binary array that describes the state of the object, SIZE IS CURRENTLY 51
			netAddr.sendMsg("/addSyncObject", "activeArray", "SCObject", "tweetObject",-1073741824, 6291456);
		});
	}
	
	clear {
		netAddr.sendMsg("/removeSyncObject","lagpass","initFlag");
		netAddr.sendMsg("/removeSyncObject","lagpass","reserveArray");		netAddr.sendMsg("/removeSyncObject","lagpass","activeArray");
		netAddr.sendMsg("changePorts",57120);
	}
	
	flush {
		netAddr.sendMsg("/removeSyncObject","lagpass","initFlag");
		netAddr.sendMsg("/removeSyncObject","lagpass","reserveArray");		netAddr.sendMsg("/removeSyncObject","lagpass","activeArray");
	}
	
	sendTweetReserveState {
		|id,state|
		netAddr.sendMsg("/setSyncArg","reserveArray",state,id);
	}
	
	sendTweetActiveState {
		|id,state|
		netAddr.sendMsg("/setSyncArg","activeArray",state,id);
	}
	
	sendReserveArray {
		|reserveArray|
		var packedIntArray;
		packedIntArray = MetaCrypt.encodeBitArray(reserveArray);
		netAddr.sendMsg("/setSyncArg","reserveArray",0,packedIntArray[0]);
		netAddr.sendMsg("/setSyncArg","reserveArray",1,packedIntArray[1]);
	}
	
	sendActiveArray {
		|activeArray|
		var packedIntArray;
		packedIntArray = MetaCrypt.encodeBitArray(activeArray);
		netAddr.sendMsg("/setSyncArg","activeArray",0,packedIntArray[0]);
		netAddr.sendMsg("/setSyncArg","activeArray",1,packedIntArray[1]);
	}
	
	// Locally sync the reserve array
	syncReserveArray {
		|reserveArray|
		mMetaLogic.syncReserveArray(reserveArray);
	}
	
	// Locally synce the active array
	syncActiveArray {
		|syncActiveArray|
		mMetaLogic.syncActiveArray(syncActiveArray);
	}
		
}